package cn.edu.qfnu.oj.web.controller;

import cn.edu.qfnu.common.exception.db.NoRecordFoundException;
import cn.edu.qfnu.common.exception.db.RecordAlreadyExistedException;
import cn.edu.qfnu.common.exception.db.WrongParameterException;
import cn.edu.qfnu.common.validation.Code;
import cn.edu.qfnu.common.validation.MailCheck;
import cn.edu.qfnu.oj.entity.Classes;
import cn.edu.qfnu.oj.entity.Student;
import cn.edu.qfnu.oj.entity.Teacher;
import cn.edu.qfnu.oj.service.ClassService;
import cn.edu.qfnu.oj.service.LoginLogService;
import cn.edu.qfnu.oj.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;

@Controller
@RequestMapping(value = "user/")
public class IndexController {

    private static final Logger log = LoggerFactory.getLogger(IndexController.class);
    private Code emailCode = Code.getInstence();

    private final UserService userService;
    private final LoginLogService loginLogService;
    private final ClassService classService;

    @Autowired
    public IndexController(UserService userService,
                           LoginLogService loginLogService, ClassService classService) {
        this.userService = userService;
        this.loginLogService = loginLogService;
        this.classService = classService;
    }


    @RequestMapping(value = "register", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, String> register(String ID, String password, String email) {

        Map<String, String> jsonMap = new HashMap<>();
        Student student = new Student(ID, password, email);
        try {
            userService.register(student);
            jsonMap.put("result", "success");
            log.info("成功注册了一个学生用户：" + ID);
        } catch (RecordAlreadyExistedException re) {
            jsonMap.put("result", "repeat");
            log.error("用户重复", re);
        }
        return jsonMap;
    }

    @RequestMapping(value = "login", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, String> login(String username, String password, String identity) {

        Map<String, String> jsonMap = new HashMap<>();

        HttpServletRequest request =
                ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        try {
            Object user = userService.login(username, password, identity);

            HttpSession session = request.getSession();

            session.setAttribute("loginUser", user);
            jsonMap.put("result", "success");
            log.info("用户" + username + "登陆成功");
        } catch (NoRecordFoundException | WrongParameterException e) {
            jsonMap.put("result", e.getMessage());
            log.error("登陆时出错", e);
        }
        //保存日志
        loginLogService.saveLog(request, username, jsonMap.get("result"));

        return jsonMap;
    }

    /**
     * 找回密码前的信息确认
     *
     * @param ID    学号或工号
     * @param email 注册邮箱
     */
    @RequestMapping(value = "check", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, String> getPassword(String ID, String email) {

        Map<String, String> jsonMap = new HashMap<>();

        if (userService.isExist(ID, email)) {
            String identifyCode = emailCode.getCodeNumber();

            emailCode.getCodeMap().put(email, identifyCode);
            if (MailCheck.sendEmail(email, identifyCode)) {
                jsonMap.put("result", "success");
                log.info("验证并发送验证码成功");
            } else {
                jsonMap.put("result", "failed");
                log.warn("发送验证码失败");
            }
        } else {
            jsonMap.put("result", "信息错误");
            log.warn("填写的信息有误");
        }
        return jsonMap;
    }

    /**
     * 找回密码：
     * 先输入学号和邮箱
     * 然后从数据库查询学生信息
     * 如果找得到就拿到他的邮箱然后向该邮箱发送验证信息
     * 拿到验证码的发送新的请求
     * 更新密码
     *
     * @param ID          学号或工号
     * @param email       学生的注册邮箱
     * @param code        邮箱验证码
     * @param newPassword 学生的新密码
     */
    @RequestMapping(value = "getPassword", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, String> getPassword(String ID, String email,
                                           String newPassword, String code) {

        Map<String, String> jsonMap = new HashMap<>();

        Object user = userService.isWho(ID, email);
        if (code.equals(emailCode.getCodeMap().get(email))) {
            if (user instanceof Student) {
                ((Student) user).setPassword(newPassword);
                userService.update(user);
                jsonMap.put("result", "success");
                log.info("重置新密码成功");
            } else if (user instanceof Teacher) {
                ((Teacher) user).setPassword(newPassword);
                userService.update(user);
                jsonMap.put("result", "success");
                log.info("重置新密码成功");
            }
        } else {
            jsonMap.put("result", "验证码错误");
            log.info("验证码错误");
        }
        return jsonMap;

    }

    @RequestMapping(value = "mailCheck", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, String> mailCheck(String mail, String code) {
        Map<String, String> jsonMap = new HashMap<>();

        if (emailCode.getCodeMap().get(mail).equals(code)) {
            jsonMap.put("result", "success");
            log.info("邮箱验证成功");
        } else {
            jsonMap.put("result", "wrong");
            log.info("验证码错误");
        }
        return jsonMap;
    }

    @RequestMapping(value = "student/modify", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, String> modify(HttpServletRequest request, Integer classNum,
                                      Integer grade, String classType, String sex, String school,
                                      String nickname) {

        Map<String, String> jsonMap = new HashMap<>();

        Student loggedStudent = (Student) request.getSession().getAttribute("loginUser");

        loggedStudent.setSex(sex);
        loggedStudent.setSchool(school);
        loggedStudent.setNickname(nickname);

        Classes classFrom = classService.isRepeat(classNum, classType, grade);
        //查重 返回新的或者已经存在的班级 更新学生
        classFrom.getStudents().add(loggedStudent);
        classService.saveOrUpdate(classFrom);

        loggedStudent.setClassFrom(classFrom);
        userService.update(loggedStudent);

        jsonMap.put("result", "success");
        log.info("修改信息成功");
        return jsonMap;
    }

    @RequestMapping(value = "teacher/modify", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, String> modify(HttpServletRequest request, String sex) {

        Map<String, String> jsonMap = new HashMap<>();

        Teacher loggedTeacher = (Teacher) request.getSession().getAttribute("loginUser");

        loggedTeacher.setSex(sex);

        userService.update(loggedTeacher);

        jsonMap.put("result", "success");
        log.info("修改信息成功");
        return jsonMap;
    }

    @RequestMapping(value = "newPwd", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, String> newPassword(HttpServletRequest request, String old, String newPwd) {
        Map<String, String> jsonMap = new HashMap<>();

        Object loginUser = request.getSession().getAttribute("loginUser");

        try {
           Object changed = userService.pwdUpdate(loginUser, old, newPwd);
           userService.update(changed);
           jsonMap.put("result", "success");
           log.info("密码修改成功");
        } catch (WrongParameterException we) {
            jsonMap.put("result", we.getMessage());
            log.error("旧密码错误");
        }
        return jsonMap;
    }
}
